AWS CDKで作成したAWS Step Functions State MachineのASL定義をjqコマンドで取得する

AWS CDKで作成したAWS Step Functions State MachineのASL定義をjqコマンドで取得する

Clock Icon2022.07.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

AWS Step Functions Localを使いたい場合、テスト対象のState MachineのASL(Amazon States Language)定義を取得する必要があります。

そこで今回は、AWS CDKでAWS Step Functionsの開発を行っている場合に、State MachineのASL定義をjqコマンドで取得する方法を確認してみました。

結論

次のコマンドを実行すれば取得できます。

$ stackName=<stackName>
$ stateMachineName=<stateMachineName>
$ jq --arg stateMachineName "$stateMachineName" \
  '.Resources[] | select(.Properties.StateMachineName == $stateMachineName)' \
  cdk.out/${stackName}.template.json | \
  jq -r .Properties.DefinitionString | jq .

やってみた

CDK SynthやCDK DeployによるBuildを行うと、StackのCloudFormation Templateがcdk.out/<stackName>.template.jsonに作成されます。

例えば次のStackの場合。

import { Construct } from 'constructs';
import { aws_stepfunctions, Stack, StackProps } from 'aws-cdk-lib';

export class AwsAppStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    // StateMachine1
    new aws_stepfunctions.StateMachine(this, 'stateMachine1', {
      stateMachineName: 'stateMachine1',
      definition: new aws_stepfunctions.Pass(this, 'pass1'),
    });

    // StateMachine2
    new aws_stepfunctions.StateMachine(this, 'stateMachine2', {
      stateMachineName: 'stateMachine2',
      definition: new aws_stepfunctions.Map(this, 'Map State', {
        itemsPath: aws_stepfunctions.JsonPath.stringAt('$.inputForMap'),
      }).iterator(new aws_stepfunctions.Pass(this, 'pass2')),
    });
  }
}

次のようなTemplate Fileが生成されます。

{
 "Resources": {
  "stateMachine1Role7BF1589E": {
   "Type": "AWS::IAM::Role",
   "Properties": {
    "AssumeRolePolicyDocument": {
     "Statement": [
      {
       "Action": "sts:AssumeRole",
       "Effect": "Allow",
       "Principal": {
        "Service": "states.ap-northeast-1.amazonaws.com"
       }
      }
     ],
     "Version": "2012-10-17"
    }
   },
   "Metadata": {
    "aws:cdk:path": "AwsAppStack/stateMachine1/Role/Resource"
   }
  },
  "stateMachine174B105B6": {
   "Type": "AWS::StepFunctions::StateMachine",
   "Properties": {
    "RoleArn": {
     "Fn::GetAtt": [
      "stateMachine1Role7BF1589E",
      "Arn"
     ]
    },
    "DefinitionString": "{\"StartAt\":\"pass1\",\"States\":{\"pass1\":{\"Type\":\"Pass\",\"End\":true}}}",
    "StateMachineName": "stateMachine1"
   },
   "DependsOn": [
    "stateMachine1Role7BF1589E"
   ],
   "Metadata": {
    "aws:cdk:path": "AwsAppStack/stateMachine1/Resource"
   }
  },
  "stateMachine2Role1C82D998": {
   "Type": "AWS::IAM::Role",
   "Properties": {
    "AssumeRolePolicyDocument": {
     "Statement": [
      {
       "Action": "sts:AssumeRole",
       "Effect": "Allow",
       "Principal": {
        "Service": "states.ap-northeast-1.amazonaws.com"
       }
      }
     ],
     "Version": "2012-10-17"
    }
   },
   "Metadata": {
    "aws:cdk:path": "AwsAppStack/stateMachine2/Role/Resource"
   }
  },
  "stateMachine23B5C198F": {
   "Type": "AWS::StepFunctions::StateMachine",
   "Properties": {
    "RoleArn": {
     "Fn::GetAtt": [
      "stateMachine2Role1C82D998",
      "Arn"
     ]
    },
    "DefinitionString": "{\"StartAt\":\"Map State\",\"States\":{\"Map State\":{\"Type\":\"Map\",\"End\":true,\"Iterator\":{\"StartAt\":\"pass2\",\"States\":{\"pass2\":{\"Type\":\"Pass\",\"End\":true}}},\"ItemsPath\":\"$.inputForMap\"}}}",
    "StateMachineName": "stateMachine2"
   },
   "DependsOn": [
    "stateMachine2Role1C82D998"
   ],
   "Metadata": {
    "aws:cdk:path": "AwsAppStack/stateMachine2/Resource"
   }
  },
  "CDKMetadata": {
   "Type": "AWS::CDK::Metadata",
   "Properties": {
    "Analytics": "v2:deflate64:H4sIAAAAAAAA/1WJzQrCMBCEn6X3ZLU9CJ49F6Q+gKzpFrc/m9JN9BDy7sZ6Ega+mfkaaM5QV/hW6/rJzvyAdAvoJlOue9JA6xDFBfaikK6oaooO1KJ7spC5DPK3W1yzYVwgdX7e9Zc5743Ux81RNuJ7glEPr/oEJcdqVGa7RQm8EHQ/fgC550rrmwAAAA=="
   },
   "Metadata": {
    "aws:cdk:path": "AwsAppStack/CDKMetadata/Default"
   }
  }
 },
 "Parameters": {
  "BootstrapVersion": {
   "Type": "AWS::SSM::Parameter::Value<String>",
   "Default": "/cdk-bootstrap/hnb659fds/version",
   "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
  }
 },
 "Rules": {
  "CheckBootstrapVersion": {
   "Assertions": [
    {
     "Assert": {
      "Fn::Not": [
       {
        "Fn::Contains": [
         [
          "1",
          "2",
          "3",
          "4",
          "5"
         ],
         {
          "Ref": "BootstrapVersion"
         }
        ]
       }
      ]
     },
     "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
    }
   ]
  }
 }
}

このうちState MachineのASL定義はハイライト部分(DefinitionString)となります。そして、Templateにおける各Resourceは、Logical IDをKeyとしたオブジェクトとなり、その配下にStateMachineNameとDefinitionStringがあります。

よって、指定の名前のStateMachineのリソースのオブジェクトを取得したい場合は、jqコマンドを次のように実行します。

$ stackName=AwsAppStack
$ stateMachineName=stateMachine1
$ jq --arg stateMachineName "$stateMachineName" \
  '.Resources[] | select(.Properties.StateMachineName == $stateMachineName)' \
  cdk.out/${stackName}.template.json
{
  "Type": "AWS::StepFunctions::StateMachine",
  "Properties": {
    "RoleArn": {
      "Fn::GetAtt": [
        "stateMachine1Role7BF1589E",
        "Arn"
      ]
    },
    "DefinitionString": "{\"StartAt\":\"pass1\",\"States\":{\"pass1\":{\"Type\":\"Pass\",\"End\":true}}}",
    "StateMachineName": "stateMachine1"
  },
  "DependsOn": [
    "stateMachine1Role7BF1589E"
  ],
  "Metadata": {
    "aws:cdk:path": "AwsAppStack/stateMachine1/Resource"
  }
}

さらにASLのみを抽出したい場合は、さらにjqコマンドへのパイプを行います。

$ stackName=AwsAppStack
$ stateMachineName=stateMachine1
$ jq --arg stateMachineName "$stateMachineName" \
  '.Resources[] | select(.Properties.StateMachineName == $stateMachineName)' \
  cdk.out/${stackName}.template.json | \
  jq -r .Properties.DefinitionString | jq .
{
  "StartAt": "pass1",
  "States": {
    "pass1": {
      "Type": "Pass",
      "End": true
    }
  }
}

もう一つのStateMachineのASLも同様に取得できます。

$ stackName=AwsAppStack
$ stateMachineName=stateMachine2
$ jq --arg stateMachineName "$stateMachineName" \
  '.Resources[] | select(.Properties.StateMachineName == $stateMachineName)' \
  cdk.out/${stackName}.template.json | \
  jq -r .Properties.DefinitionString | jq .
{
  "StartAt": "Map State",
  "States": {
    "Map State": {
      "Type": "Map",
      "End": true,
      "Iterator": {
        "StartAt": "pass2",
        "States": {
          "pass2": {
            "Type": "Pass",
            "End": true
          }
        }
      },
      "ItemsPath": "$.inputForMap"
    }
  }
}

おわりに

AWS CDKで作成したAWS Step Functions State MachineのASL定義をjqコマンドで取得する方法を確認してみました。

AWS CLIのstepfunctions describe-state-machineコマンドを使ってもASLを取得できなくは無いのでしょうが、AWS CDKの開発環境であればローカルにBuildがされるのであれば、せっかくならそっちから取得してしまえということでjqを使ってみました。

以上

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.